package com.bai.li;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

import java.util.Arrays;
import java.util.List;

/**
 * 声明这个类为一个切面:
 * 需要把该类放入到 IOC 容器中@Component,然后再声明为一个切面@Aspect
 */
public class Logging {
    //声明一个方案是一个前置通知:在目标方法开始之前执行
    public void beforeMethod(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        List<Object> list = Arrays.asList(joinPoint.getArgs());
        System.out.println("The method" + methodName + " begin" + list);
    }

    //后置通知:在目标方法之后(无论是否发生异常),执行的通知;
    //在后置通知中还不能进行结果的返回;需要在返回通知中进行设置;
    public void afterMethod(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The method" + methodName + " end");
    }

    //在方法正常执行结束后返回的通知;
    // 返回的通知是可以访问到返回值
    public void afterReturning(JoinPoint joinPoint,Object result) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The method" + methodName + " end "+result);
    }

    //在目标方法出现异常时会执行的代码
    //可以访问到异常对象,且可以指定在出现特定异常时再执行代码
    public void afterThrowing(JoinPoint joinPoint,Exception e) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The method" + methodName + " exception "+e);
    }

    //环绕通知需要携带ProceedingJoinPoint 类型的参数
    //环绕通知类似于动态代理的全过程:
    //且环绕通知必须有返回值;返回值为目标方法的返回值;
    public Object aroung(ProceedingJoinPoint pjp) {
        Object result=null;
        String methodName=pjp.getSignature().getName();
        try{
            //前置通知
            System.out.println(" the method"+methodName+" begin "+Arrays.asList(pjp.getArgs()));
            //执行目标方法
            result=pjp.proceed();
            //返回通知
            System.out.println("the  method"+methodName+" end "+result);
        }catch (Throwable e){
            //异常通知
            System.out.println("exception" + e);
            throw new RuntimeException();
        }
        //后置通知
        System.out.println("the method "+methodName+" end ");
        return result;
    }
}
